﻿#region Copyright & licence

// This file is part of Refix.
// 
// Refix is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
// 
// Refix is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
// 
// You should have received a copy of the GNU Lesser General Public
// License along with Refix.  If not, see <http://www.gnu.org/licenses/>.
// 
// Copyright (C) 2010-11 David Musgrove and others.

#endregion

using System;
using System.IO;
using System.Linq;

using Refix.Core.Repository;
using Refix.RepositoryBrowser.Properties;

namespace Refix.RepositoryBrowser.Models
{
    public class RepositoryModelFactory : IRepositoryModelFactory
    {
        public ILocalRepository Repository { get; set; }

        public RepositoryModelFactory()
        {
            Repository = new LocalRepository();
        }

        public RepositoryModelFactory(string directory)
        {
            SetDirectory(directory);
        }

        public void SetDirectory(string directory)
        {
            Repository = new LocalRepository(directory);
        }

        public RepositoryItem ConstructModel(IRepositoryModel model)
        {
            model.ReportStatus(Resources.PARSING_REPOSITORY);
            var repositoryItem = new RepositoryItem
                        {
                            RootDirectory = Repository.BaseDirectory,
                            Directory = Repository.BaseDirectory
                        };
            if (!Directory.Exists(Repository.BaseDirectory))
            {
                return repositoryItem;
            }
            var rootDirectory = new DirectoryInfo(Repository.BaseDirectory);
            AddChildren(repositoryItem, rootDirectory, "", null, model);
            return repositoryItem;
        }

        private bool AddChildren(RepositoryItem item, DirectoryInfo directory, string assemblyName, Component component, IRepositoryModel model)
        {
            model.ReportStatus(Resources.PARSING_REPOSITORY + ": " + directory.FullName);
            bool hasComponent = false;
            foreach (var subDirectory in directory.GetDirectories())
            {
                string subAssemblyName = assemblyName;
                string name = subDirectory.Name;
                var child = new RepositoryItem
                            {
                                Name = name,
                                Parent = item,
                                Directory = subDirectory.FullName
                            };
                if (component != null && component.Versions.Any(v => v.Number == name))
                {
                    child.ComponentVersion = component.Versions.Single(v => v.Number == name);
                    item.Children.Add(child);
                    continue;
                }
                if (subAssemblyName != "") subAssemblyName += ".";
                subAssemblyName += name;
                var childComponent = Repository.GetComponent(subAssemblyName, false);
                if (AddChildren(child, subDirectory, subAssemblyName, childComponent, model) || childComponent != null)
                {
                    child.Component = childComponent;
                    item.Children.Add(child);
                    hasComponent = true;
                }
            }
            return hasComponent;
        }
    }
}